package com.ttg.web.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ttg.common.config.DynamicTableNameHelper;
import com.ttg.common.entities.BaseResult;
import com.ttg.common.entities.RattingTask;
import com.ttg.common.enums.ConditionsClassEnum;
import com.ttg.common.enums.TaskEnum;
import com.ttg.common.utils.DateTimeUtil;
import com.ttg.model.dto.GenerateFilesDTO;
import com.ttg.model.pojo.BankPrivatePrimitive;
import com.ttg.model.pojo.BankPublicPrimitive;
import com.ttg.model.pojo.BankPublicPrimitiveAum;
import com.ttg.model.pojo.VipInfo;
import com.ttg.model.vo.open.QueryVipTagConfigVo;
import com.ttg.web.dao.BankPrivatePrimitiveDao;
import com.ttg.web.dao.BankPublicPrimitiveAumDao;
import com.ttg.web.dao.BankPublicPrimitiveDao;
import com.ttg.web.dao.VipInfoDao;
import com.ttg.web.service.TzgService;
import com.ttg.web.service.VipInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
@Slf4j
public class TzgServiceImpl implements TzgService {


    @Value("${sftp.tzgZip}")
    private String tzgZip;
    @Value("${sftp.tzgZipFilePrefix}")
    private String tzgZipFilePrefix;
    @Autowired
    private BankPrivatePrimitiveDao bankPrivatePrimitiveDao;
    @Autowired
    private BankPublicPrimitiveAumDao bankPublicPrimitiveAumDao;
    @Autowired
    private BankPublicPrimitiveDao bankPublicPrimitiveDao;

    @Autowired
    private VipInfoService vipInfoService;
    @Autowired
    private VipInfoDao vipInfoDao;


    private static final int PAGE_SIZE = 50_000;

    private static final int ZIP_BUFFER_SIZE = 128 * 1024;

    @Override
    @RattingTask(taskEnum = TaskEnum.GENERATE_TZG_ZIP)
    public void generateFilesByTblValueHandler(GenerateFilesDTO reqDto) throws IOException {
        String s = DateTimeUtil.formatYYYYMMDD(LocalDate.now());
        String d = DateTimeUtil.formatYYYYMMDD(LocalDate.now().minusMonths(1));
        String s1 = tzgZipFilePrefix + s + ".zip";
        String s2 = tzgZipFilePrefix + s + ".ok";
        String d1 = tzgZipFilePrefix + d + ".zip";
        String d2 = tzgZipFilePrefix + d + ".ok";
        try (ZipOutputStream zos = new ZipOutputStream(
                new BufferedOutputStream(new FileOutputStream(tzgZip + s1), ZIP_BUFFER_SIZE)
        )) {
            getBankPrivatePrimitiveValues(reqDto, zos);
            if ((Objects.isNull(reqDto.getTabValue()) && CollectionUtils.isEmpty(reqDto.getTabValues())) || ConditionsClassEnum.BANK_PUBLIC_PRIMITIVE.getValue() == reqDto.getTabValue() || reqDto.getTabValues().contains(ConditionsClassEnum.BANK_PUBLIC_PRIMITIVE.getValue())) {
                bankPublicPrimitive(zos);
            }
            if ((Objects.isNull(reqDto.getTabValue()) && CollectionUtils.isEmpty(reqDto.getTabValues())) || reqDto.getTabValue() == 9998 || reqDto.getTabValues().contains(9998)) {
                getVipTagConfig(zos);
            }
            if ((Objects.isNull(reqDto.getTabValue()) && CollectionUtils.isEmpty(reqDto.getTabValues())) || reqDto.getTabValue() == 9999 || reqDto.getTabValues().contains(9999)) {
                getAppCouponVip(zos);
            }
            if ((Objects.isNull(reqDto.getTabValue()) && CollectionUtils.isEmpty(reqDto.getTabValues())) || reqDto.getTabValue() == 9997 || reqDto.getTabValues().contains(9997)) {
                getBankPublicPrimitiveAumValues(zos);
            }
            Path t = Paths.get(tzgZip + s2);
            if (Files.exists(t)) {
                Files.setLastModifiedTime(t, FileTime.from(Instant.now()));
            } else {
                Files.createFile(t);
            }
            Files.deleteIfExists(Paths.get(tzgZip+d1));
            Files.deleteIfExists(Paths.get(tzgZip+d2));
            log.info("{} 导出完成",s1);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }

    }

    private void getBankPublicPrimitiveAumValues(ZipOutputStream zos) throws IOException  {
        List<String> strs= new ArrayList<String>(
                Arrays.asList("01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16"));
        for (String str : strs) {
            bankPublicPrimitiveAum(str,zos);

        }
    }

    private void bankPublicPrimitiveAum(String value, ZipOutputStream zos) throws IOException {
        log.info( "tbl_bank_public_primitive_aum_"+value+ ".unl");
        zos.putNextEntry(new ZipEntry("tbl_bank_public_primitive_aum_"+value+ ".unl"));
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(zos, StandardCharsets.UTF_8), 8192
        );
        long starId = 0L;
        List<BankPublicPrimitiveAum> list;
        do {
            Map<String, String> tableSuffix = DynamicTableNameHelper.getTableSuffix();
            tableSuffix.put("tbl_bank_public_primitive_aum", value);
            DynamicTableNameHelper.setTableSuffix(tableSuffix);
            list= bankPublicPrimitiveAumDao.list(new LambdaQueryWrapper<BankPublicPrimitiveAum>()
                    .gt(BankPublicPrimitiveAum::getId,starId)
                    .last("LIMIT "+PAGE_SIZE));
            for (BankPublicPrimitiveAum data : list) {
                writer.write(data.toFieIds());
                writer.newLine();
                starId = data.getId();
            }
        } while (!list.isEmpty());
        writer.flush();
        zos.closeEntry();
        log.info("表导出完成:{},id:{}", "tbl_bank_public_primitive_aum_"+value, starId);
    }

    private void getVipTagConfig(ZipOutputStream zos) throws IOException {
        log.info("gxd_tag_info.unl");
        BaseResult baseResult = vipInfoService.queryVipTagConfigTzg();
        zos.putNextEntry(new ZipEntry("gxd_tag_info.unl"));
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(zos, StandardCharsets.UTF_8), 8192
        );
        List<QueryVipTagConfigVo> list = (List<QueryVipTagConfigVo>) baseResult.getData();
        for (QueryVipTagConfigVo fieIds : list) {
            writer.write(fieIds.toFieIds());
            writer.newLine();
        }
        writer.flush();
        zos.closeEntry();
        log.info("标签全表导出完成,gxd_tag_info.unl");
    }

    private void getAppCouponVip(ZipOutputStream zos) throws IOException {
        log.info("tbl_gxd_app_coupon_vip.unl");
        BaseResult baseResult = vipInfoService.queryVipTagConfig();
        zos.putNextEntry(new ZipEntry("tbl_gxd_app_coupon_vip.unl"));
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(zos, StandardCharsets.UTF_8), 8192
        );
        long starId = 0L;
        List<VipInfo> list;
        do {
            list = vipInfoDao.tblGxdAppCouponVip(
                    PAGE_SIZE, starId);
            for (VipInfo vipInfo : list) {
                writer.write(vipInfo.toFieIds());
                writer.newLine();
                starId = vipInfo.getVipId();
            }
        } while (!list.isEmpty());
        writer.flush();
        zos.closeEntry();
        log.info("个人客户全表导出完成,tbl_gxd_app_coupon_vip.unl");
    }

    private void getBankPrivatePrimitiveValues(GenerateFilesDTO reqDto, ZipOutputStream zos) throws IOException {
        List<Integer> bankPrivatePrimitiveValues = new ArrayList<>();
        if (Objects.isNull(reqDto.getTabValue()) && CollectionUtils.isEmpty(reqDto.getTabValues())) {
            bankPrivatePrimitiveValues = ConditionsClassEnum.getBankPrivatePrimitiveValues();
        }
        if (!reqDto.getTabValues().isEmpty()) {
            for (Integer tabValue : reqDto.getTabValues()) {
                if (ConditionsClassEnum.needSumByAgent(tabValue)) {
                    bankPrivatePrimitiveValues.add(tabValue);
                }
            }
        }
        if (ConditionsClassEnum.needSumByAgent(reqDto.getTabValue())) {
            bankPrivatePrimitiveValues.add(reqDto.getTabValue());
        }
        if ((Objects.isNull(reqDto.getTabValue()) && CollectionUtils.isEmpty(reqDto.getTabValues())) || !bankPrivatePrimitiveValues.isEmpty()) {
            for (Integer value : bankPrivatePrimitiveValues) {
                bankPrivatePrimitive(value, zos);
            }
        }
    }

    private void bankPrivatePrimitive(Integer value, ZipOutputStream zos) throws IOException {
        log.info(ConditionsClassEnum.getByValue(value).getTableName() + ".unl");
        zos.putNextEntry(new ZipEntry(ConditionsClassEnum.getByValue(value).getTableName() + ".unl"));
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(zos, StandardCharsets.UTF_8), 8192
        );
        long starId = 0L;
        List<BankPrivatePrimitive> list;
        do {
            list = bankPrivatePrimitiveDao.tblBankPrivatePrimitive(
                    ConditionsClassEnum.getByValue(value).getTableName(),
                    PAGE_SIZE, starId);
            for (BankPrivatePrimitive primitive : list) {
                writer.write(primitive.toFieIds());
                writer.newLine();
                starId = primitive.getId();
            }
        } while (!list.isEmpty());
        writer.flush();
        zos.closeEntry();
        log.info("表导出完成:{},id:{}", ConditionsClassEnum.getByValue(value).getTableName(), starId);
    }


    private void bankPublicPrimitive(ZipOutputStream zos) throws IOException {
        log.info(ConditionsClassEnum.BANK_PUBLIC_PRIMITIVE.getTableName() + ".unl");
        zos.putNextEntry(new ZipEntry(ConditionsClassEnum.BANK_PUBLIC_PRIMITIVE.getTableName() + ".unl"));
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(zos, StandardCharsets.UTF_8), 8192
        );
        long starId = 0L;
        List<BankPublicPrimitive> list;
        do {
            list = bankPublicPrimitiveDao.bankPublicPrimitive(
                    PAGE_SIZE, starId);
            for (BankPublicPrimitive fieIds : list) {
                writer.write(fieIds.toFieIds());
                writer.newLine();
                starId = fieIds.getId();
            }
        } while (!list.isEmpty());
        writer.flush();
        zos.closeEntry();
        log.info("表导出完成:{},id:{}", ConditionsClassEnum.BANK_PUBLIC_PRIMITIVE.getTableName(), starId);
    }

}
